package com.jeff.utils.security;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * author：duff
 * version：1.0.0
 * date：2017/8/31
 * desc：
 */
public class AESUtil {
    private static final String VIPARA = "0102030405060708";
    private static final byte[] RAW_KEY = {84, 65, -33, 92, 57, 90, -104, 0, 112, 74, 69, -53,
            106, -122, -107, -95};
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";

    /**
     * 对字符串进行AES加密
     *
     * @param content 未加密的字符串
     * @return 加密后的字符串
     * @throws Exception e
     */
    public static String encrypt(String content) throws Exception {
        return encrypt(RAW_KEY, content);
    }

    public static String encrypt(byte[] rawKey, String content) throws Exception {
        byte[] encrypted = encrypt(rawKey, content.getBytes());
        return toHex(encrypted);
    }

    /**
     * 解密
     *
     * @param content 已加密的字符串
     * @return 解密后的字符串
     * @throws Exception e
     */
    public static String decrypt(String content) throws Exception {
        return decrypt(RAW_KEY, content);
    }

    public static String decrypt(byte[] rawKey, String content) throws Exception {
        byte[] encrypted = toByte(content);
        byte[] result = decrypt(rawKey, encrypted);
        return new String(result);
    }

    private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
        IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
        SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, zeroIv);
        byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
        IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
        SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, zeroIv);
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

    private static byte[] toByte(String hexString) {
        int len = hexString.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++) {
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), SecurityUtil.RADIX_16).byteValue();
        }
        return result;
    }

    private static String toHex(byte[] buf) {
        if (buf == null) {
            return "";
        }

        StringBuffer result = new StringBuffer(2 * buf.length);
        for (int i = 0; i < buf.length; i++) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }

    private final static String HEX = "0123456789ABCDEF";

    private static void appendHex(StringBuffer sb, byte b) {
        final int flagOfLowByte = 0x0f;
        final int shift = 4;
        sb.append(HEX.charAt((b >> shift) & flagOfLowByte)).append(HEX.charAt(b & flagOfLowByte));
    }

}
